#pragma once

#include <inttypes.h>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

class IMUTime {
 private:
  friend class boost::serialization::access;
  int year, month, day, hour, minute, second, microsecond;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &year;
    ar &month;
    ar &day;
    ar &hour;
    ar &minute;
    ar &second;
    ar &microsecond;
  }

 public:
  IMUTime(int _year, int _month, int _day, int _hour, int _minute, int _second,
          int _microsecond) {
    year = _year;
    month = _month;
    day = _day;
    hour = _hour;
    minute = _minute;
    second = _second;
    microsecond = _microsecond;
  }
  IMUTime() {}
  void create(int _year, int _month, int _day, int _hour, int _minute,
              int _second, int _microsecond) {
    year = _year;
    month = _month;
    day = _day;
    hour = _hour;
    minute = _minute;
    second = _second;
    microsecond = _microsecond;
  }
  void fromSource(uint16_t s0, uint16_t s1, uint16_t s2, uint16_t s3) {
    hour = s0 / 100;
    month = s0 % 100;
    day = s1 / 100;
    hour = s1 % 100;
    minute = s2 / 100;
    second = s2 % 100;
    microsecond = s3;
  }
  int get_year() { return year; }
  int get_month() { return month; }
  int get_day() { return day; }
  int get_hour() { return hour; }
  int get_minute() { return minute; }
  int get_second() { return second; }
  int get_microsecond() { return microsecond; }
};

class IMUAcceleration {
 private:
  friend class boost::serialization::access;
  short ax, ay, az;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &ax;
    ar &ay;
    ar &az;
  }

 public:
  IMUAcceleration(short _ax, short _ay, short _az) {
    ax = _ax;
    ay = _ay;
    az = _az;
  }
  IMUAcceleration() {}
  void create(short _ax, short _ay, short _az) {
    ax = _ax;
    ay = _ay;
    az = _az;
  }
  void fromSource(uint16_t s0, uint16_t s1, uint16_t s2) {
    ax = s0;
    ay = s1;
    az = s2;
  }
  short get_ax() { return ax; }
  short get_ay() { return ay; }
  short get_az() { return az; }
};

class IMUAngularVelocity {
 private:
  friend class boost::serialization::access;
  short wx, wy, wz;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &wx;
    ar &wy;
    ar &wz;
  }

 public:
  IMUAngularVelocity(short _wx, short _wy, short _wz) {
    wx = _wx;
    wy = _wy;
    wz = _wz;
  }
  IMUAngularVelocity() {}
  void fromSource(uint16_t s0, uint16_t s1, uint16_t s2) {
    wx = s0;
    wy = s1;
    wz = s2;
  }
  void create(short _wx, short _wy, short _wz) {
    wx = _wx;
    wy = _wy;
    wz = _wz;
  }
  short get_wx() { return wx; }
  short get_wy() { return wy; }
  short get_wz() { return wz; }
};

class IMUAngleOutput {
 private:
  friend class boost::serialization::access;
  int Roll, Pitch, Yaw;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &Roll;
    ar &Pitch;
    ar &Yaw;
  }

 public:
  IMUAngleOutput(int _Roll, int _Pitch, int _Yaw) {
    Roll = _Roll;
    Pitch = _Pitch;
    Yaw = _Yaw;
  }
  IMUAngleOutput() {}
  void create(int _Roll, int _Pitch, int _Yaw) {
    Roll = _Roll;
    Pitch = _Pitch;
    Yaw = _Yaw;
  }
  void fromSource(uint16_t s0, uint16_t s1, uint16_t s2) {
    Roll = s0;
    Pitch = s1;
    Yaw = s2;
  }
  int get_Roll() { return Roll; }
  int get_Pitch() { return Pitch; }
  int get_Yaw() { return Yaw; }
};

class IMUMagneticOutput {
 private:
  friend class boost::serialization::access;
  int hx, hy, hz;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &hx;
    ar &hy;
    ar &hz;
  }

 public:
  IMUMagneticOutput(int _hx, int _hy, int _hz) {
    hx = _hx;
    hy = _hy;
    hz = _hz;
  }
  IMUMagneticOutput() {}
  void create(int _hx, int _hy, int _hz) {
    hx = _hx;
    hy = _hy;
    hz = _hz;
  }
  void fromSource(uint16_t s0, uint16_t s1, uint16_t s2) {
    hx = s0;
    hy = s1;
    hz = s2;
  }
  int get_hx() { return hx; }
  int get_hy() { return hy; }
  int get_hz() { return hz; }
};

class IMUPortStatusDataOutput {
 private:
  friend class boost::serialization::access;
  int D0, D1, D2, D3;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &D0;
    ar &D1;
    ar &D2;
    ar &D3;
  }

 public:
  IMUPortStatusDataOutput(int _D0, int _D1, int _D2, int _D3) {
    D0 = _D0;
    D1 = _D1;
    D2 = _D2;
    D3 = _D3;
  }
  IMUPortStatusDataOutput() {}
  void create(int _D0, int _D1, int _D2, int _D3) {
    D0 = _D0;
    D1 = _D1;
    D2 = _D2;
    D3 = _D3;
  }
  void fromSource(uint16_t s0, uint16_t s1, uint16_t s2, uint16_t s3) {
    D0 = s0;
    D1 = s1;
    D2 = s2;
    D3 = s3;
  }
  int get_D0() { return D0; }
  int get_D1() { return D1; }
  int get_D2() { return D2; }
  int get_D3() { return D3; }
};

class IMUPressureAndHeightOutput {
 private:
  friend class boost::serialization::access;
  int P, H;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &P;
    ar &H;
  }

 public:
  IMUPressureAndHeightOutput(int _P, int _H) {
    P = _P;
    H = _H;
  }
  IMUPressureAndHeightOutput() {}
  void create(int _P, int _H) {
    P = _P;
    H = _H;
  }
  void fromSource(uint16_t PL, uint16_t PH, uint16_t HL, uint16_t HH) {
    P = PH;
    P <<= 8;
    P |= PL;
    H = HH;
    H <<= 8;
    H |= HL;
  }
  int get_P() { return P; }
  int get_H() { return H; }
};

class IMULatitudeAndLongitudeOutput {
 private:
  friend class boost::serialization::access;
  long Latitude, Longitude;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &Latitude;
    ar &Longitude;
  }

 public:
  IMULatitudeAndLongitudeOutput(long _Latitude, long _Longitude) {
    _Latitude = Latitude;
    _Longitude = Longitude;
  }
  IMULatitudeAndLongitudeOutput() {}
  void create(long _Latitude, long _Longitude) {
    _Latitude = Latitude;
    _Longitude = Longitude;
  }
  void fromSource(uint16_t LonL, uint16_t LonH, uint16_t LatL, uint16_t LatH) {
    Longitude = LonH;
    Longitude <<= 8;
    Longitude |= LonL;
    Latitude = LatH;
    Latitude <<= 8;
    Latitude |= LatL;
  }
  long get_Latitude() { return Latitude; }
  long get_Longitude() { return Longitude; }
};

class IMUGroundSpeedOutput {
 private:
  friend class boost::serialization::access;
  long GPSHeight, GPSYaw, GPSV;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &GPSHeight;
    ar &GPSYaw;
    ar &GPSV;
  }

 public:
  IMUGroundSpeedOutput(long _GPSHeight, long _GPSYaw, long _GPSV) {
    GPSHeight = _GPSHeight;
    GPSYaw = _GPSYaw;
    GPSV = _GPSV;
  }
  IMUGroundSpeedOutput() {}
  void create(long _GPSHeight, long _GPSYaw, long _GPSV) {
    GPSHeight = _GPSHeight;
    GPSYaw = _GPSYaw;
    GPSV = _GPSV;
  }
  void fromSource(uint16_t s0, uint16_t s1, uint16_t VH, uint16_t VL) {
    GPSHeight = s0;
    GPSYaw = s1;
    GPSV = VH;
    GPSV <<= 8;
    GPSV |= VL;
  }
  long get_GPSHeight() { return GPSHeight; }
  long get_GPSYAW() { return GPSYaw; }
  long get_GPSV() { return GPSV; }
};

class IMUQuaternionOutput {
 private:
  friend class boost::serialization::access;
  int Q0, Q1, Q2, Q3;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &Q0;
    ar &Q1;
    ar &Q2;
    ar &Q3;
  }

 public:
  IMUQuaternionOutput(int _Q0, int _Q1, int _Q2, int _Q3) {
    Q0 = _Q0;
    Q1 = _Q1;
    Q2 = _Q2;
    Q3 = _Q3;
  }
  IMUQuaternionOutput() {}
  void create(int _Q0, int _Q1, int _Q2, int _Q3) {
    Q0 = _Q0;
    Q1 = _Q1;
    Q2 = _Q2;
    Q3 = _Q3;
  }
  void fromSource(int s0, int s1, int s2, int s3) {
    Q0 = s0;
    Q1 = s1;
    Q2 = s2;
    Q3 = s3;
  }
  int get_Q0() { return Q0; }
  int get_Q1() { return Q1; }
  int get_Q2() { return Q2; }
  int get_Q3() { return Q3; }
};

class IMUSatellitePositioningAccuracyOutput {
 private:
  friend class boost::serialization::access;
  int SN, PDOP, HDOP, VDOP;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &SN;
    ar &PDOP;
    ar &HDOP;
    ar &VDOP;
  }

 public:
  IMUSatellitePositioningAccuracyOutput(int _SN, int _PDOP, int _HDOP,
                                        int _VDOP) {
    SN = _SN;
    PDOP = _PDOP;
    HDOP = _HDOP;
    VDOP = _VDOP;
  }
  IMUSatellitePositioningAccuracyOutput() {}
  void create(int _SN, int _PDOP, int _HDOP, int _VDOP) {
    SN = _SN;
    PDOP = _PDOP;
    HDOP = _HDOP;
    VDOP = _VDOP;
  }
  int get_SN() { return SN; }
  int get_PDOP() { return PDOP; }
  int get_HDOP() { return HDOP; }
  int get_VDOP() { return VDOP; }
};

class IMUTemperature {
 private:
  friend class boost::serialization::access;
  int Temperature;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &Temperature;
  }

 public:
  IMUTemperature(int _Temperature) { Temperature = _Temperature; }
  IMUTemperature() {}
  void create(int _Temperature) { Temperature = _Temperature; }
  void fromSource(uint16_t s0) { Temperature = s0; }
  int get_Temperature() { return Temperature; }
};

class IMUData {
 private:
  friend class boost::serialization::access;
  IMUTime Time;
  IMUAcceleration Acceleration;
  IMUAngularVelocity AngularVelocity;
  IMUAngleOutput AngleOutput;
  IMUMagneticOutput MagneticOutput;
  IMUPortStatusDataOutput PortStatusDataOutput;
  IMUPressureAndHeightOutput PressureAndHeightOutput;
  IMUQuaternionOutput QuaternionOutput;
  IMUSatellitePositioningAccuracyOutput SatellitePositioningAccuracyOutput;
  IMUTemperature Temperature;
  template <class Archive>
  void serialize(Archive &ar, const unsigned int version) {
    ar &Time;
    ar &Acceleration;
    ar &AngularVelocity;
    ar &AngleOutput;
    ar &MagneticOutput;
    ar &PortStatusDataOutput;
    ar &PressureAndHeightOutput;
    ar &QuaternionOutput;
    ar &SatellitePositioningAccuracyOutput;
  }

 public:
  IMUData(
      IMUTime _Time, IMUAcceleration _Acceleration,
      IMUAngularVelocity _AngularVelocity, IMUAngleOutput _AngleOutput,
      IMUMagneticOutput _MagneticOutput,
      IMUPortStatusDataOutput _PortStatusDataOutput,
      IMUPressureAndHeightOutput _PressureAndHeightOutput,
      IMUQuaternionOutput _QuaternionOutput,
      IMUSatellitePositioningAccuracyOutput _SatellitePositioningAccuracyOutput,
      IMUTemperature _Temperature) {
    Time = _Time;
    Acceleration = _Acceleration;
    AngularVelocity = _AngularVelocity;
    AngleOutput = _AngleOutput;
    MagneticOutput = _MagneticOutput;
    PortStatusDataOutput = _PortStatusDataOutput;
    PressureAndHeightOutput = _PressureAndHeightOutput;
    QuaternionOutput = _QuaternionOutput;
    SatellitePositioningAccuracyOutput = _SatellitePositioningAccuracyOutput;
    Temperature = _Temperature;
  }
  IMUData(IMUTime _Time, IMUAcceleration _Acceleration,
          IMUAngularVelocity _AngularVelocity, IMUAngleOutput _AngleOutput,
          IMUMagneticOutput _MagneticOutput,
          IMUPortStatusDataOutput _PortStatusDataOutput,
          IMUPressureAndHeightOutput _PressureAndHeightOutput,
          IMUQuaternionOutput _QuaternionOutput, IMUTemperature _Temperature) {
    Time = _Time;
    Acceleration = _Acceleration;
    AngularVelocity = _AngularVelocity;
    AngleOutput = _AngleOutput;
    MagneticOutput = _MagneticOutput;
    PortStatusDataOutput = _PortStatusDataOutput;
    PressureAndHeightOutput = _PressureAndHeightOutput;
    QuaternionOutput = _QuaternionOutput;
    Temperature = _Temperature;
  }
  IMUData() {}
  void create(
      IMUTime _Time, IMUAcceleration _Acceleration,
      IMUAngularVelocity _AngularVelocity, IMUAngleOutput _AngleOutput,
      IMUMagneticOutput _MagneticOutput,
      IMUPortStatusDataOutput _PortStatusDataOutput,
      IMUPressureAndHeightOutput _PressureAndHeightOutput,
      IMUQuaternionOutput _QuaternionOutput,
      IMUSatellitePositioningAccuracyOutput _SatellitePositioningAccuracyOutput,
      IMUTemperature _Temperature) {
    Time = _Time;
    Acceleration = _Acceleration;
    AngularVelocity = _AngularVelocity;
    AngleOutput = _AngleOutput;
    MagneticOutput = _MagneticOutput;
    PortStatusDataOutput = _PortStatusDataOutput;
    PressureAndHeightOutput = _PressureAndHeightOutput;
    QuaternionOutput = _QuaternionOutput;
    SatellitePositioningAccuracyOutput = _SatellitePositioningAccuracyOutput;
    Temperature = _Temperature;
  }
  void create(IMUTime _Time, IMUAcceleration _Acceleration,
              IMUAngularVelocity _AngularVelocity, IMUAngleOutput _AngleOutput,
              IMUMagneticOutput _MagneticOutput,
              IMUPortStatusDataOutput _PortStatusDataOutput,
              IMUPressureAndHeightOutput _PressureAndHeightOutput,
              IMUQuaternionOutput _QuaternionOutput,
              IMUTemperature _Temperature) {
    Time = _Time;
    Acceleration = _Acceleration;
    AngularVelocity = _AngularVelocity;
    AngleOutput = _AngleOutput;
    MagneticOutput = _MagneticOutput;
    PortStatusDataOutput = _PortStatusDataOutput;
    PressureAndHeightOutput = _PressureAndHeightOutput;
    QuaternionOutput = _QuaternionOutput;
    Temperature = _Temperature;
  }
  IMUTime get_Time() { return Time; }
  IMUAcceleration get_Acceleration() { return Acceleration; }
  IMUAngleOutput get_AngleOutput() { return AngleOutput; }
  IMUMagneticOutput get_MagneticOutput() { return MagneticOutput; }
  IMUPortStatusDataOutput get_PortStatusDataOutput() {
    return PortStatusDataOutput;
  }
  IMUPressureAndHeightOutput get_PressureAndHeightOutput() {
    return PressureAndHeightOutput;
  }
  IMUQuaternionOutput get_QuaternionOutput() { return QuaternionOutput; }
  IMUSatellitePositioningAccuracyOutput
  get_SatellitePositioningAccuracyOutput() {
    return SatellitePositioningAccuracyOutput;
  }
  IMUTemperature get_Temperature() { return Temperature; }
};
